package link.jfire.socket.socketserver.storage;

import link.jfire.baseutil.collection.ByteCache;
import link.jfire.baseutil.reflect.ReflectUtil;
import link.jfire.socket.socketserver.bus.BusinessCommand;
import link.jfire.socket.socketserver.bus.ServerChannelInfo;
import sun.misc.Unsafe;

@SuppressWarnings("restriction")
public class Entry
{
    private volatile int               state;
    public static final int            TAKEN         = 1;
    public static final int            FREEFORUSE    = 0;
    private volatile WritePacket       writePacket;
    private volatile byte              actionType;
    private volatile ServerChannelInfo serverChannelInfo;
    private volatile byte              command;
    private volatile byte              requestResult = BusinessCommand.REQUEST_SUCCESS;
    private ByteCache                  businessData  = new ByteCache(128);
    private static Unsafe              unsafe        = ReflectUtil.getUnsafe();
    private static long                offset        = ReflectUtil.getFieldOffset("state", Entry.class);
    
    /**
     * 设置新的数据，会将状态刷新为freeforuse
     * 
     * @param actionType
     * @param command
     * @param serverChannelInfo
     */
    public void setNewData(byte actionType, byte command, WritePacket writePacket, ServerChannelInfo serverChannelInfo)
    {
        this.actionType = actionType;
        this.writePacket = writePacket;
        this.command = command;
        this.serverChannelInfo = serverChannelInfo;
        // 这里无需插入写写屏障。虽然这四个语句可能会乱序执行，但是由于生产者需要发布，消费者才能看到。而这些操作都发生在发布之前，所以保证了可以被消费者正确发现
        state = FREEFORUSE;
    }
    
    public byte getActionType()
    {
        return actionType;
    }
    
    public ServerChannelInfo getServerChannelInfo()
    {
        return serverChannelInfo;
    }
    
    public byte getCommand()
    {
        return command;
    }
    
    public ByteCache getBusinessData()
    {
        return businessData;
    }
    
    public WritePacket getWritePacket()
    {
        return writePacket;
    }
    
    /**
     * 获取该消息的使用权，true代表成功，false代表失败
     * 
     * @return
     */
    public boolean take()
    {
        if (state == FREEFORUSE)
        {
            return unsafe.compareAndSwapInt(this, offset, FREEFORUSE, TAKEN);
        }
        else
        {
            return false;
        }
    }
    
    public byte getRequestResult()
    {
        return requestResult;
    }
    
    public void failRequest()
    {
        requestResult = BusinessCommand.REQUEST_FAIL;
    }
    
}
